﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinesweeperApp.Properties;
using System.IO;

namespace MinesweeperApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Resources.startMessage);

            string[,] matrix = CreateQuestionMatrix();
            string[,] actualMatrix = CreateActualMatrix();

            PrintMatrix(matrix);

            //PrintMatrix(actualMatrix);

            int numberOfSuccessfulOpenings = 0;

            MinesweeperDBEntities context = new MinesweeperDBEntities();
            
            while (true)
            {
                Console.Write(Resources.enterRowCollumnMessage);
                string input = Console.ReadLine();
                if (input == Resources.exitCommand)
                {
                    Console.Write(Resources.goodBye);
                    break;
                }
                if (input == Resources.restartCommand)
                {
                    // resetting the matrix
                    numberOfSuccessfulOpenings = 0;
                    matrix = CreateQuestionMatrix();
                    actualMatrix = CreateActualMatrix();
                    PrintMatrix(matrix);
                    continue;
                }
                if (input == Resources.topCommand)
                {
                    ProcessTopCommand(context);
                    PrintMatrix(matrix);
                    continue;
                }


                OpenQuestionResult result = ProcessSingleUserInput(input, matrix, actualMatrix);
                switch (result)
                {
                    case OpenQuestionResult.Failure:

                        PrintMatrix(matrix);
                        Result resToInsert = new Result();
                        Console.WriteLine(string.Format(Resources.boom, numberOfSuccessfulOpenings));
                        resToInsert.name = Console.ReadLine();
                        resToInsert.openedCells = numberOfSuccessfulOpenings;
                        resToInsert.dateCreated = DateTime.Now;
                        resToInsert.id = Guid.NewGuid();
                        context.Result.AddObject(resToInsert);
                        context.SaveChanges();

                        ProcessTopCommand(context);

                        // resetting the matrix
                        numberOfSuccessfulOpenings = 0;
                        matrix = CreateQuestionMatrix();
                        actualMatrix = CreateActualMatrix();

                        Console.Write(Resources.startMessage);
                        PrintMatrix(matrix);


                        break;
                    case OpenQuestionResult.Success:
                        numberOfSuccessfulOpenings++;
                        PrintMatrix(matrix);
                        break;
                    case OpenQuestionResult.IllegalMove:
                        break;
                    case OpenQuestionResult.LegalMove:
                        break;
                    default:
                        break;
                }
            }
        }
  
        private static void ProcessTopCommand(MinesweeperDBEntities context)
        {
            Console.WriteLine(Resources.scoreboard);
            foreach (var res in context.Result.OrderByDescending(res => res.openedCells).Take(5))
            {
                Console.WriteLine(string.Format("{0} --> {1} cells.", res.name, res.openedCells));
            }
        }

        private static string[,] CreateActualMatrix()
        {
            string[,] actualMatrix = new string[5, 10];

            Random random = new Random();

            for (int counter = 0; counter < 15; counter++)
            {
                int row = random.Next(5);
                int column = random.Next(10);

                if (string.IsNullOrEmpty(actualMatrix[row, column]))
                {
                    actualMatrix[row, column] = "*";
                }
            }
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    if (actualMatrix[i, j] != "*")
                    {
                        actualMatrix[i, j] = DetermineMinesCount(i, j, actualMatrix);
                    }
                }
            }

            return actualMatrix;
        }

        private static string DetermineMinesCount(int row, int column, string[,] matrix)
        {
            int result = 0;
            if (row - 1 >= 0 && row - 1 < 5 && column - 1 >= 0 && column - 1 < 10 && matrix[row - 1, column - 1] == "*")
            {
                result++;
            }
            if (row - 1 >= 0 && row - 1 < 5 && column >= 0 && column < 10 && matrix[row - 1, column] == "*")
            {
                result++;
            }
            if (row - 1 >= 0 && row - 1 < 5 && column + 1 >= 0 && column + 1 < 10 && matrix[row - 1, column + 1] == "*")
            {
                result++;
            }
            if (row >= 0 && row < 5 && column - 1 >= 0 && column - 1 < 10 && matrix[row, column - 1] == "*")
            {
                result++;
            }
            if (row >= 0 && row < 5 && column + 1 >= 0 && column + 1 < 10 && matrix[row, column + 1] == "*")
            {
                result++;
            }
            if (row + 1 >= 0 && row + 1 < 5 && column - 1 >= 0 && column + 1 < 10 && matrix[row + 1, column - 1] == "*")
            {
                result++;
            }
            if (row + 1 >= 0 && row + 1 < 5 && column >= 0 && column < 10 && matrix[row + 1, column] == "*")
            {
                result++;
            }
            if (row + 1 >= 0 && row + 1 < 5 && column + 1 >= 0 && column + 1 < 10 && matrix[row + 1, column + 1] == "*")
            {
                result++;
            }
            if (result == 0)
            {
                return " ";
            }
            else
            {
                return result.ToString();
            }

        }

        private static string[,] CreateQuestionMatrix()
        {
            string[,] matrix = new string[5, 10];

            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    matrix[i, j] = "?";
                }
            }

            return matrix;
        }

        private static void PrintMatrix(string[,] matrixToPrint)
        {
            Console.WriteLine("    0 1 2 3 4 5 6 7 8 9");
            Console.WriteLine("   ---------------------");
            for (int i = 0; i < 5; i++)
            {
                Console.Write(string.Format("{0} |", i));
                for (int j = 0; j < 10; j++)
                {
                    Console.Write(string.Format(" {0}", matrixToPrint[i, j]));
                }
                Console.Write(" |");
                Console.WriteLine();
            }
            Console.WriteLine("   ---------------------");
        }

        private static void PopulateEmptySpacesInMatrix(string[,] matrixToPopulate)
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    if (string.IsNullOrEmpty(matrixToPopulate[i, j]))
                    {
                        matrixToPopulate[i, j] = " ";
                    }

                }
            }
        }

        private static OpenQuestionResult ProcessSingleUserInput(string inputRow, string[,] matrix, string[,] actualMatrix)
        {
            string[] ints = inputRow.Trim().Split(' ');
            if (ints.Length != 2)
            {
                Console.WriteLine(Resources.illegalMove);
                return OpenQuestionResult.IllegalMove;
            }
            int row;
            if (!int.TryParse(ints[0], out row))
            {
                Console.WriteLine(Resources.illegalMove);
                return OpenQuestionResult.IllegalMove;
            }
            int column;
            if (!int.TryParse(ints[1], out column))
            {
                Console.WriteLine(Resources.illegalMove);
                return OpenQuestionResult.IllegalMove;
            }
            if (row < 0 || row > 4)
            {
                Console.WriteLine(Resources.illegalMove);
                return OpenQuestionResult.IllegalMove;
            }
            if (column < 0 || column > 9)
            {
                Console.WriteLine(Resources.illegalMove);
                return OpenQuestionResult.IllegalMove;
            }
            if (matrix[row, column] != "?")
            {
                Console.WriteLine(Resources.illegalMove);
                return OpenQuestionResult.IllegalMove;
            }
            if (actualMatrix[row, column] == "*")
            {
                for (int i = 0; i < 5; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        if (matrix[i, j] == "?" && actualMatrix[i, j] != "*")
                        {
                            matrix[i, j] = "-";
                        }
                        if (matrix[i, j] == "?" && actualMatrix[i, j] == "*")
                        {
                            matrix[i, j] = "*";
                        }
                    }
                }

                return OpenQuestionResult.Failure;
            }
            matrix[row, column] = actualMatrix[row, column];
            return OpenQuestionResult.Success;
        }

        enum OpenQuestionResult
        {
            Failure,
            Success,
            IllegalMove,
            LegalMove
        }


    }
}
